package com.kernowsoft.wavefx.specdraw;

import com.kernowsoft.wavefx.R;

import android.content.Context;
import android.content.res.TypedArray;
import android.graphics.Bitmap;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.DashPathEffect;
import android.graphics.Paint;
import android.graphics.Paint.Align;
import android.graphics.Path;
import android.graphics.RectF;
import android.util.AttributeSet;
import android.util.Log;
import android.view.View;

public class SpecDraw extends View {

	private final static String TAG = "SpecDraw";
	private Paint painter;
	private RectF rect;

	// attributes:
	private boolean mShowColorbar;
	private boolean mLogScale;
	private int mColorbarPosition;
	private int mPlotMargin;

	// draw settings
	//private Float[] mFreqTicks;
	private float[] mFreqRange = new float[2];

	// spec data:
	SpecData mSpecData = null;
	Bitmap mBitmap = null;
	Paint mBitmapPainter = new Paint();

	public SpecDraw(Context context, AttributeSet attrs) {
		super(context, attrs);

		mSpecData = null;
		mBitmap = null;
		mLogScale = true;

		mFreqRange[0] = 0.0f;
		mFreqRange[1] = 0.65f;

		// get attributes from xml file. Do this via call the
		// obtainStyledAttributes as this applied themes and
		// resolves resource references:
		TypedArray a = context.getTheme().obtainStyledAttributes(attrs,
				R.styleable.SpecDrawAttrs, 0, 0);

		if (a != null) {
			try {
				mPlotMargin = a.getInt(R.styleable.SpecDrawAttrs_plotMargin, 10);

				mShowColorbar = a.getBoolean(R.styleable.SpecDrawAttrs_showColorbar,
						false);

				mColorbarPosition = a.getInt(
						R.styleable.SpecDrawAttrs_colorbarPosition, 1);

				mLogScale = a.getBoolean(R.styleable.SpecDrawAttrs_logScale, true);
			} finally {
				// typed array is a shared resource, so recycle after use.
				a.recycle();
			}
		}
		init();
	}

	public SpecDraw(Context context) {
		super(context);
		init();
	}

	public SpecDraw(Context context, AttributeSet attrs, int defStyle) {
		super(context, attrs, defStyle);
		init();
	}

	private void init() {
		// initialise painter oBjects, etc.

		// create default painter:
		painter = new Paint();

		// rectangle for drawing arcs:
		rect = new RectF();
	}

	public void setSpecData(SpecData specdata) {
		this.mSpecData = specdata;
		mBitmap = null; // null the bitmap to force a refresh
		// this.refreshDrawableState();
		this.invalidate();

	}

	private void createBitmap() {

		int col;
		double dat;
		// float logfac = 0.0372f; // 0.041 / 1.1
		float logfac = 0.034f; // picked for best fit of central circle with
								// linear scale.

		Float[] freq_ticks;
		if (mLogScale) {
			freq_ticks = new Float[] { 0.04f, 0.0625f, 0.1f, 0.166f, 0.33f,
					0.65f };
		} else {
			freq_ticks = new Float[] { 0.04f, 0.1f, 0.2f, 0.3f, 0.4f, 0.5f,
					0.65f };
		}

		if (isInEditMode()) {
			Log.d(TAG, "IN EDIT MODE");
			mSpecData = new SpecData();
			mSpecData.spec2d = testdat2;
			mSpecData.numDirs = 24;
			mSpecData.numFreqs = 30;
			mSpecData.freqs = new float[] { 0.041f, 0.0451f, 0.04961f,
					0.054571f, 0.0600281f, 0.06603091f, 0.072634f, 0.0798974f,
					0.08788714f, 0.09667586f, 0.10634344f, 0.11697778f,
					0.12867556f, 0.14154312f, 0.15569743f, 0.17126717f,
					0.18839389f, 0.20723328f, 0.22795661f, 0.25075227f,
					0.2758275f, 0.30341025f, 0.33375127f, 0.3671264f,
					0.40383904f, 0.444222944f, 0.48864523f, 0.5375097f,
					0.5912607f, 0.6503868f };
			mSpecData.dirs = new float[] { 0.000000f, 0.261799f, 0.523599f,
					0.785398f, 1.047198f, 1.308997f, 1.570796f, 1.832596f,
					2.094395f, 2.356194f, 2.617994f, 2.879793f, 3.141593f,
					3.403392f, 3.665191f, 3.926991f, 4.188790f, 4.450590f,
					4.712389f, 4.974188f, 5.235988f, 5.497787f, 5.759587f,
					6.021386f };
			mSpecData.dth = (float)(2.0f * Math.PI / mSpecData.numDirs);
			
			mSpecData.windDir = 110.0f;
			mSpecData.windSpeed = 12.5f;
			mSpecData.sitename = "Test Site";

		}

		if (mSpecData == null) {
			mBitmap = null;
			Log.d(TAG, "SPEC DATA IS NULL - RETURNING");
			return;
		}

		if (getWidth() == 0 || getHeight() == 0) {
			Log.i(TAG, "Width or height are zero - not drawing");
			return;
		}

		long t = System.currentTimeMillis();
		Log.i(TAG, "Starting draw");

		mBitmap = Bitmap.createBitmap(getWidth(), getHeight(),
				Bitmap.Config.ARGB_8888);
		Canvas canvas = new Canvas(mBitmap);

		painter.setStrokeWidth(2);
		painter.setStyle(Paint.Style.FILL);
		painter.setAntiAlias(true);

		Path p = new Path();

		// centre of view:
		int x0 = getWidth() / 2;
		int y0 = getHeight() / 2;

		// calculate frequencies:
		int nk = mSpecData.numFreqs;
		float f1 = 0.041f;
		float[] freqs = new float[nk];
		freqs[0] = f1;
		for (int i = 1; i < nk; i++)
			freqs[i] = freqs[i - 1] * 1.1f;

		float[] r;
		float[] r1 = new float[nk];
		float[] r2 = new float[nk];
		if (mLogScale) {
			// calculate log spaced frequencies:
			r = new float[nk];
			for (int ik = 0; ik < nk; ik++) {
				r[ik] = (float) Math.log10(freqs[ik] / logfac);
			}
		} else {
			// linear spacing
			r = freqs;
		}

		// first dir and dtheta
		float th1 = 0.0f;
		int nth = mSpecData.numDirs;
		float dth = 360.0f / nth;
		float dthr = (float) Math.toRadians(dth);

		float x, y;
		// float r1, r2;
		float r0x = 30; // distance from centre of plot for first (0Hz) ring

		float maxr = mLogScale ? (float) Math.log10(mFreqRange[1] / logfac)
				: mFreqRange[1];

		float rfac = (Math.min(getWidth(), getHeight()) / 2f - mPlotMargin - r0x)
				/ maxr;
		// / r[nk - 1]; // factor to convert to radii to real screen
		// coords

		for (int ik = 0; ik < nk; ik++) {
			r1[ik] = (freqs[ik] - 0.5f * (freqs[ik] * 1.1f - freqs[ik]));
			r2[ik] = (freqs[ik] + 0.5f * (freqs[ik] * 1.1f - freqs[ik]));
			if (mLogScale) {
				r1[ik] = (float) Math.log10(r1[ik] / logfac);
				r2[ik] = (float) Math.log10(r2[ik] / logfac);
			}
			r1[ik] = r0x + rfac * r1[ik];
			r2[ik] = r0x + rfac * r2[ik];
		}

		// loop over directions:
		for (int ith = 0; ith < nth; ith++) {

			float th = th1 + dth * ith - dth / 2; // - 1/2 dth to align on bin
													// centres
			// convert to cartesian:
			th = 360 - th;
			float thr = (float) Math.toRadians(th);

			// loop over frequencies:
			for (int ik = 0; ik < nk; ik++) {

				// check range:
				if (freqs[ik] > mFreqRange[1])
					continue;

				// clear path:
				p.reset();

				// move to bottom of inner radius:
				x = x0 + (float) Math.cos(thr) * r1[ik];
				y = y0 + (float) Math.sin(thr) * r1[ik];
				p.moveTo(x, y);

				// line from inner to outer radius, lower angle:
				x = x0 + (float) Math.cos(thr) * r2[ik];
				y = y0 + (float) Math.sin(thr) * r2[ik];
				p.lineTo(x, y);

				// outer radius arc, clockwise:
				rect.set(x0 - r2[ik], y0 - r2[ik], x0 + r2[ik], y0 + r2[ik]);
				p.arcTo(rect, th, dth);

				// line back to inner radius, upper angle:
				x = x0 + (float) Math.cos(thr + dthr) * r1[ik];
				y = y0 + (float) Math.sin(thr + dthr) * r1[ik];
				p.lineTo(x, y);

				// inner arc, anti-clockwise
				rect.set(x0 - r1[ik], y0 - r1[ik], x0 + r1[ik], y0 + r1[ik]);
				p.arcTo(rect, th + dth, -dth);

				p.close();

				// determine colour of segment from data:
				dat = mSpecData.spec2d[ik][ith];

				if (dat < 0.01)
					col = Color.TRANSPARENT;
				else if (dat < 0.1)
					col = Color.rgb(0, 80, 170);
				else if (dat < 0.2)
					col = Color.rgb(0, 100, 210);
				else if (dat < 0.5)
					col = Color.rgb(0, 138, 232);
				else if (dat < 1.0)
					col = Color.rgb(26, 180, 205);
				else if (dat < 2.0)
					col = Color.rgb(115, 205, 105);
				else if (dat < 5.0)
					col = Color.rgb(209, 231, 1);
				else if (dat < 10.0)
					col = Color.rgb(219, 199, 0);
				else if (dat < 20.0)
					col = Color.rgb(231, 171, 0);
				else if (dat < 50.0)
					col = Color.rgb(242, 138, 0);
				else if (dat < 100.0)
					col = Color.rgb(252, 106, 0);
				else if (dat < 200.0)
					col = Color.rgb(254, 47, 0);
				else
					col = Color.rgb(227, 0, 0);

				painter.setStyle(Paint.Style.FILL);
				painter.setColor(col);
				canvas.drawPath(p, painter);

				/*
				 * if (dat >= 0.01) { painter.setStyle(Paint.Style.STROKE);
				 * painter.setColor(Color.GRAY); canvas.drawPath(p, painter); }
				 */
			}
		}

		/**************************************************************
		 * draw axes TODO: Draw this to a separate bitmap once, then overlay
		 * with an alpha of 180
		 **************************************************************/

		// rose lines:
		float rose1 = r0x + r[0] * rfac;
		float rose2 = r0x + r[nk - 1] * rfac;
		painter.setStyle(Paint.Style.STROKE);
		painter.setColor(Color.GRAY);
		painter.setPathEffect(new DashPathEffect(new float[] { 3, 3 }, 0));
		painter.setAlpha(180);

		for (int i = 0; i < 12; i++) {
			float th = (float) Math.toRadians(i * 30f);
			float x1 = x0 + (float) Math.cos(th) * rose1;
			float x2 = x0 + (float) Math.cos(th) * rose2;
			float y1 = y0 + (float) Math.sin(th) * rose1;
			float y2 = y0 + (float) Math.sin(th) * rose2;

			canvas.drawLine(x1, y1, x2, y2, painter);
		}

		// freq lines:
		Float[] radii;
		if (mLogScale) {
			radii = new Float[nk];
			for (int i = 0; i < freq_ticks.length; i++)
				radii[i] = (float) Math.log10(freq_ticks[i] / logfac);
		} else {
			radii = freq_ticks;
		}

		for (int i = 0; i < freq_ticks.length; i++) {
			if (freq_ticks[i] > mFreqRange[1])
				break;
			canvas.drawCircle(x0, y0, r0x + radii[i] * rfac, painter);
		}

		// freq labels:
		float th_lbl = 60;
		float rotang;
		float th_lbl_r = (float) Math.toRadians(th_lbl);

		for (int i = 0; i < freq_ticks.length; i++) {
			if (freq_ticks[i] > mFreqRange[1])
				break;

			x = x0 + (float) Math.cos(th_lbl_r) * (radii[i] * rfac + r0x);
			y = y0 + (float) Math.sin(th_lbl_r) * (radii[i] * rfac + r0x);
			rotang = 270 + 60;
			canvas.rotate(rotang, x, y);

			painter.setTextAlign(Align.CENTER);
			painter.setStrokeWidth(0);
			painter.setPathEffect(null);
			painter.setAlpha(180);
			painter.setColor(Color.DKGRAY);

			canvas.drawText(String.format("%.1fs", 1.0 / freq_ticks[i]), x, y,
					painter);
			canvas.rotate(-rotang, x, y);

			x = x0 + (float) Math.cos(-th_lbl_r) * (radii[i] * rfac + r0x);
			y = y0 + (float) Math.sin(-th_lbl_r) * (radii[i] * rfac + r0x);
			rotang = 90 - 60;
			canvas.rotate(rotang, x, y);
			canvas.drawText(String.format("%.2fHz", freq_ticks[i]), x, y,
					painter);
			canvas.rotate(-rotang, x, y);
		}

		// add integrated parameters:
		float[] mn = mSpecData.integrate();
		float hsig = 4.0f * (float) Math.sqrt(mn[0]);
		float tm = mn[0] / mn[1];
		float tz = (float) Math.sqrt(mn[0] / mn[2]);

		x = x0;
		y = 20;
		painter.setTextAlign(Align.CENTER);
		painter.setAlpha(255);
		canvas.drawText(String.format("Hsig: %.1fm, Tm: %.1fs, Tz: %.1fs",
				hsig, tm, tz), x, y, painter);

		
		
		// draw wind arrow:
		float mag =  mSpecData.windSpeed * (r0x * 0.95f) / 15.0f;
		x = (float)Math.cos(Math.toRadians(450 - mSpecData.windDir)) * mag;
		y = (float)Math.sin(Math.toRadians(450 - mSpecData.windDir)) * mag;
		painter.setColor(Color.BLACK);
		painter.setStrokeWidth(3);
		canvas.drawLine(x0, y0, x0 + x, y0 + y, painter);
		
		
		t = System.currentTimeMillis() - t;
		Log.i(TAG, String.format("Ending draw: %dms", t));
	}

	@Override
	protected void onDraw(Canvas canvas) {

		// recreate the bitmap if it is null
		if (mBitmap == null) {
			Log.d(TAG, "Creating new spectral bitmap image");
			createBitmap();
		}

		if (mBitmap != null)
			canvas.drawBitmap(mBitmap, 0, 0, mBitmapPainter);
		else
			Log.d(TAG, "Bitmap is numm - not drawing.");
	}

	@Override
	protected void onSizeChanged(int w, int h, int oldw, int oldh) {
		super.onSizeChanged(w, h, oldw, oldh);

		// force redraw of bitmap by setting it to null
		mBitmap = null;

	}

	// Getters and setters:
	public boolean hasColorbar() {
		return mShowColorbar;
	}

	public int getColorbarPosition() {
		return mColorbarPosition;
	}

	public boolean isLogScale() {
		return mLogScale;
	}

	public void setHasColorbar(boolean show) {
		this.mShowColorbar = show;
		invalidate();
		requestLayout();
	}

	public void setColorbarPosition(int pos) {
		this.mColorbarPosition = pos;
		invalidate();
		requestLayout();
	}

	public void setLogScale(boolean logscale) {
		if (mLogScale != logscale) {
			// dont redraw if we have not changed anything...
			this.mLogScale = logscale;
			mBitmap = null; // force bitmap to be recreated
			invalidate(); // force a redraw
		}

		// requestLayout();
	}

	public void setMaxFreq(float freq) {
		mFreqRange[1] = freq;
		mBitmap = null;
		invalidate();
	}

	private static final Float testdat2[][] = {
			{ 0.0207f, 0.00742f, 0.00148f, 0.000175f, 1.37e-05f, 7.8e-07f,
					2.02e-08f, 3.77e-11f, 5.68e-13f, 4.34e-14f, 1.06e-14f,
					3.28e-15f, 9.69e-16f, 2.7e-16f, 6.37e-17f, 1.28e-15f,
					4.92e-13f, 1.17e-09f, 1.06e-05f, 0.000314f, 0.00167f,
					0.00726f, 0.0191f, 0.0281f },
			{ 0.45f, 0.127f, 0.0192f, 0.00176f, 0.000107f, 5.11e-06f,
					1.15e-07f, 1.69e-10f, 3.14e-12f, 2.16e-13f, 5.28e-14f,
					1.64e-14f, 4.86e-15f, 1.36e-15f, 3.23e-16f, 6.81e-15f,
					3.24e-12f, 5.63e-09f, 7.07e-05f, 0.00302f, 0.0189f, 0.152f,
					0.496f, 0.713f },
			{ 1.55f, 0.381f, 0.0605f, 0.00551f, 0.00029f, 1.23e-05f, 3.08e-07f,
					7.67e-10f, 2.65e-11f, 7.08e-13f, 1.64e-13f, 5.24e-14f,
					1.56e-14f, 4.41e-15f, 1.02e-15f, 3.28e-14f, 1.98e-11f,
					1.56e-08f, 0.000169f, 0.00938f, 0.075f, 1.08f, 3.37f, 3.83f },
			{ 6.51f, 0.798f, 0.0933f, 0.00896f, 0.000634f, 3.46e-05f,
					1.13e-06f, 5.65e-09f, 2.54e-10f, 3.14e-12f, 2.24e-13f,
					6.68e-14f, 1.95e-14f, 5.41e-15f, 1.31e-15f, 1.33e-13f,
					9.93e-11f, 2.5e-08f, 9.2e-05f, 0.00655f, 0.15f, 5.86f,
					23.1f, 26.2f },
			{ 16.1f, 1.58f, 0.142f, 0.0114f, 0.000887f, 6.07e-05f, 1.93e-06f,
					1.81e-08f, 1.05e-09f, 1.96e-11f, 2.54e-13f, 1.03e-13f,
					2.86e-14f, 7.22e-15f, 1.82e-15f, 8.28e-15f, 2.75e-10f,
					7.33e-08f, 2.52e-05f, 0.00215f, 0.209f, 11.5f, 54.9f, 69.1f },
			{ 31.4f, 3.46f, 0.248f, 0.0217f, 0.00298f, 0.000334f, 1.73e-05f,
					2.39e-07f, 9.56e-09f, 1.89e-10f, 2.02e-12f, 4.3e-13f,
					9.06e-14f, 2.05e-14f, 4.65e-15f, 4.26e-14f, 9.94e-10f,
					3.08e-07f, 2.14e-05f, 0.000806f, 0.271f, 15.1f, 81.2f,
					114.0f },
			{ 30.9f, 4.71f, 0.443f, 0.046f, 0.00971f, 0.00172f, 0.000154f,
					3.99e-06f, 1.51e-07f, 5.25e-10f, 1.58e-11f, 2.62e-12f,
					5.87e-13f, 1.31e-13f, 2.49e-14f, 6.57e-14f, 4.96e-10f,
					4.27e-07f, 2.81e-05f, 0.00031f, 0.163f, 9.57f, 57.6f, 94.3f },
			{ 23.9f, 6.26f, 1.12f, 0.163f, 0.0274f, 0.0043f, 0.000377f,
					1.4e-05f, 4.33e-07f, 9.74e-09f, 2.45e-10f, 3.06e-11f,
					4.9e-12f, 9.83e-13f, 1.88e-13f, 6.54e-14f, 1.74e-10f,
					1.82e-07f, 1.24e-05f, 0.000166f, 0.0636f, 4.05f, 27.8f,
					52.0f },
			{ 17.6f, 7.74f, 2.66f, 0.634f, 0.104f, 0.0119f, 0.00076f,
					2.05e-05f, 1.2e-06f, 4.23e-08f, 1.6e-09f, 2.11e-10f,
					2.95e-11f, 4.8e-12f, 9.22e-13f, 1.51e-13f, 7.68e-11f,
					1.24e-07f, 8.07e-06f, 0.000142f, 0.0274f, 1.52f, 12.2f,
					25.6f },
			{ 10.6f, 6.94f, 3.9f, 1.68f, 0.435f, 0.0562f, 0.00299f, 5.93e-05f,
					3.44e-06f, 1.19e-07f, 5.27e-09f, 6.01e-10f, 7.62e-11f,
					1.13e-11f, 2.01e-12f, 2.83e-13f, 5.88e-11f, 1.4e-07f,
					8.95e-06f, 0.000183f, 0.018f, 0.632f, 5.24f, 11.1f },
			{ 6.88f, 5.89f, 3.82f, 1.86f, 0.649f, 0.117f, 0.00839f, 0.000157f,
					9.16e-06f, 3.63e-07f, 1.58e-08f, 1.49e-09f, 1.6e-10f,
					2.15e-11f, 3.53e-12f, 4.42e-13f, 3.97e-11f, 8.8e-08f,
					7.25e-06f, 0.000279f, 0.0141f, 0.37f, 2.99f, 6.08f },
			{ 4.39f, 4.6f, 3.48f, 1.8f, 0.624f, 0.126f, 0.0113f, 0.000346f,
					2.08e-05f, 8.9e-07f, 4.09e-08f, 3.02e-09f, 2.57e-10f,
					2.93e-11f, 4.37e-12f, 6.3e-13f, 1.18e-10f, 6.93e-08f,
					1.47e-05f, 0.000489f, 0.0105f, 0.242f, 1.88f, 3.61f },
			{ 2.74f, 3.27f, 2.98f, 1.72f, 0.662f, 0.14f, 0.0131f, 0.000539f,
					3.96e-05f, 1.78e-06f, 7.41e-08f, 4.23e-09f, 2.72e-10f,
					2.69e-11f, 3.38e-12f, 1.6e-12f, 8.11e-10f, 2.26e-07f,
					4.11e-05f, 0.000825f, 0.0102f, 0.212f, 1.36f, 2.25f },
			{ 1.85f, 2.26f, 2.25f, 1.43f, 0.614f, 0.15f, 0.016f, 0.000769f,
					6.37e-05f, 3.31e-06f, 1.15e-07f, 4.81e-09f, 2.13e-10f,
					1.78e-11f, 1.98e-12f, 8.04e-12f, 3.56e-09f, 7.58e-07f,
					8.65e-05f, 0.00121f, 0.0122f, 0.224f, 1.0f, 1.51f },
			{ 1.27f, 1.54f, 1.6f, 1.14f, 0.533f, 0.144f, 0.0172f, 0.000994f,
					8.7e-05f, 4.99e-06f, 1.55e-07f, 4.9e-09f, 1.4e-10f,
					9.71e-12f, 1.19e-12f, 3.91e-11f, 9.65e-09f, 1.95e-06f,
					0.000123f, 0.00152f, 0.0151f, 0.243f, 0.744f, 1.0f },
			{ 0.859f, 1.01f, 1.08f, 0.87f, 0.448f, 0.135f, 0.0178f, 0.00119f,
					0.000104f, 6.32e-06f, 1.88e-07f, 4.56e-09f, 8.45e-11f,
					3.99e-12f, 6.67e-13f, 1.12e-10f, 1.62e-08f, 3.34e-06f,
					0.000121f, 0.00157f, 0.0189f, 0.241f, 0.541f, 0.677f },
			{ 0.571f, 0.66f, 0.722f, 0.627f, 0.362f, 0.123f, 0.0183f, 0.00138f,
					0.000114f, 7.13e-06f, 2.14e-07f, 4.06e-09f, 4.65e-11f,
					7.97e-13f, 6.66e-13f, 1.88e-10f, 2.02e-08f, 3.27e-06f,
					8.67e-05f, 0.00132f, 0.0224f, 0.197f, 0.365f, 0.454f },
			{ 0.365f, 0.419f, 0.465f, 0.43f, 0.282f, 0.109f, 0.0185f, 0.00157f,
					0.000118f, 7e-06f, 2.06e-07f, 3.17e-09f, 2.24e-11f,
					5.58e-14f, 7.99e-13f, 1.61e-10f, 1.85e-08f, 1.71e-06f,
					4.41e-05f, 0.000934f, 0.0246f, 0.141f, 0.231f, 0.297f },
			{ 0.23f, 0.264f, 0.297f, 0.292f, 0.212f, 0.0942f, 0.0184f,
					0.00177f, 0.000119f, 6.17e-06f, 1.64e-07f, 2.02e-09f,
					1.11e-11f, 9.44e-15f, 5.47e-13f, 7.37e-11f, 1.16e-08f,
					5.6e-07f, 1.6e-05f, 0.000595f, 0.0232f, 0.0932f, 0.144f,
					0.193f },
			{ 0.135f, 0.155f, 0.174f, 0.178f, 0.14f, 0.0684f, 0.0153f,
					0.00162f, 9.63e-05f, 4.2e-06f, 9.71e-08f, 9.18e-10f,
					4.44e-12f, 3.6e-15f, 1.63e-13f, 1.79e-11f, 2.93e-09f,
					1.09e-07f, 3.86e-06f, 0.000408f, 0.015f, 0.0508f, 0.0781f,
					0.113f },
			{ 0.0794f, 0.0922f, 0.103f, 0.108f, 0.0901f, 0.0474f, 0.0115f,
					0.00128f, 6.81e-05f, 2.46e-06f, 4.24e-08f, 3.08e-10f,
					1.07e-12f, 1.49e-15f, 2.72e-14f, 2.85e-12f, 2.84e-10f,
					1.4e-08f, 7.98e-07f, 0.000346f, 0.00785f, 0.0248f, 0.0405f,
					0.0635f },
			{ 0.0461f, 0.0543f, 0.0606f, 0.0652f, 0.0564f, 0.0315f, 0.00824f,
					0.000953f, 4.75e-05f, 1.45e-06f, 1.67e-08f, 9.29e-11f,
					2.11e-13f, 3.62e-16f, 2.57e-15f, 2.95e-13f, 2.83e-11f,
					2.58e-09f, 2.49e-07f, 0.000228f, 0.00366f, 0.0111f,
					0.0208f, 0.0347f },
			{ 0.027f, 0.0327f, 0.037f, 0.04f, 0.0353f, 0.0203f, 0.00558f,
					0.000674f, 3.39e-05f, 9.35e-07f, 7.75e-09f, 3.56e-11f,
					6.53e-14f, 9.38e-17f, 6.35e-16f, 7.58e-14f, 9.89e-12f,
					1.15e-09f, 1.58e-07f, 0.000113f, 0.00162f, 0.00493f,
					0.0106f, 0.019f },
			{ 0.0166f, 0.0204f, 0.0233f, 0.0253f, 0.0225f, 0.013f, 0.00363f,
					0.000445f, 2.25e-05f, 6.09e-07f, 4.53e-09f, 1.98e-11f,
					3.51e-14f, 4.78e-17f, 3.28e-16f, 3.95e-14f, 5.46e-12f,
					6.65e-10f, 9.82e-08f, 6.3e-05f, 0.000897f, 0.00277f,
					0.00617f, 0.0114f },
			{ 0.0103f, 0.0127f, 0.0145f, 0.0157f, 0.014f, 0.00808f, 0.00225f,
					0.000276f, 1.4e-05f, 3.78e-07f, 2.81e-09f, 1.23e-11f,
					2.18e-14f, 2.97e-17f, 2.04e-16f, 2.45e-14f, 3.39e-12f,
					4.13e-10f, 6.1e-08f, 3.91e-05f, 0.000557f, 0.00172f,
					0.00383f, 0.00707f },
			{ 0.0064f, 0.00788f, 0.00899f, 0.00976f, 0.00866f, 0.00502f,
					0.0014f, 0.000171f, 8.69e-06f, 2.35e-07f, 1.75e-09f,
					7.65e-12f, 1.35e-14f, 1.84e-17f, 1.26e-16f, 1.52e-14f,
					2.11e-12f, 2.56e-10f, 3.79e-08f, 2.43e-05f, 0.000346f,
					0.00107f, 0.00238f, 0.00439f },
			{ 0.00397f, 0.00489f, 0.00558f, 0.00606f, 0.00538f, 0.00312f,
					0.000869f, 0.000106f, 5.39e-06f, 1.46e-07f, 1.08e-09f,
					4.75e-12f, 8.4e-15f, 1.14e-17f, 7.85e-17f, 9.45e-15f,
					1.31e-12f, 1.59e-10f, 2.35e-08f, 1.51e-05f, 0.000215f,
					0.000662f, 0.00148f, 0.00273f },
			{ 0.00247f, 0.00304f, 0.00347f, 0.00376f, 0.00334f, 0.00193f,
					0.000539f, 6.61e-05f, 3.35e-06f, 9.05e-08f, 6.73e-10f,
					2.95e-12f, 5.22e-15f, 7.1e-18f, 4.87e-17f, 5.87e-15f,
					8.12e-13f, 9.88e-11f, 1.46e-08f, 9.37e-06f, 0.000133f,
					0.000411f, 0.000917f, 0.00169f },
			{ 0.00153f, 0.00189f, 0.00215f, 0.00234f, 0.00207f, 0.0012f,
					0.000335f, 4.1e-05f, 2.08e-06f, 5.62e-08f, 4.18e-10f,
					1.83e-12f, 3.24e-15f, 4.41e-18f, 3.02e-17f, 3.64e-15f,
					5.04e-13f, 6.14e-11f, 9.07e-09f, 5.82e-06f, 8.28e-05f,
					0.000255f, 0.000569f, 0.00105f },
			{ 0.000951f, 0.00117f, 0.00134f, 0.00145f, 0.00129f, 0.000746f,
					0.000208f, 2.55e-05f, 1.29e-06f, 3.49e-08f, 2.59e-10f,
					1.14e-12f, 2.01e-15f, 2.74e-18f, 1.88e-17f, 2.26e-15f,
					3.13e-13f, 3.81e-11f, 5.63e-09f, 3.61e-06f, 5.14e-05f,
					0.000159f, 0.000353f, 0.000653f } };
}
